package com.ruoyi.web.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.web.domain.DeviceAccessCode;
import com.ruoyi.web.domain.DeviceAccessVisitor;
import com.ruoyi.web.domain.MonitorArea;
import com.ruoyi.web.domain.MonitorCamera;
import com.ruoyi.web.domain.dto.DeviceAccessCodeDto;
import com.ruoyi.web.domain.dto.GetAuthUrlDto;
import com.ruoyi.web.mapper.DeviceAccessCodeMapper;
import com.ruoyi.web.mapper.DeviceAccessVisitorMapper;
import com.ruoyi.web.service.IDeviceAccessCodeService;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.service.IDeviceAccessVisitorService;
import com.ruoyi.web.service.IMonitorAreaService;
import com.ruoyi.web.service.IMonitorCameraService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class DeviceAccessCodeServiceImpl extends ServiceImpl<DeviceAccessCodeMapper, DeviceAccessCode> implements IDeviceAccessCodeService {

    @Autowired
    private DeviceAccessCodeMapper deviceAccessCodeMapper;

    @Autowired
    private DeviceAccessVisitorMapper deviceAccessVisitorMapper;

    @Autowired
    private IDeviceAccessVisitorService visitorService;

    @Autowired
    private IMonitorAreaService monitorAreaService;
    @Autowired
    private AliyunLiveService aliyunLiveService;

    @Override
    public List<DeviceAccessCode> selectByCondition(DeviceAccessCodeDto condition) {
        Long userId = SecurityUtils.getUserId();
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser user = loginUser.getUser();
        List<SysRole> roles = user.getRoles();
        if(roles != null){
            List<Long> roleIds = roles.stream().map(SysRole::getRoleId).collect(Collectors.toList());
            if(roleIds.contains(1L)){
                //管理员
                condition.setAdminFlag("1");
            }else{
                condition.setAdminFlag("0");
                condition.setSubmitUserId(userId);
            }
        }else{
            condition.setAdminFlag("0");
            condition.setSubmitUserId(userId);
        }



        return deviceAccessCodeMapper.selectByCondition(condition);
    }

    @Override
    public List<DeviceAccessCode> pageList(Page page, DeviceAccessCode condition) {
        return deviceAccessCodeMapper.pageList(page, condition);
    }

    @Override
    public DeviceAccessCode detail(Long baseId) {
        DeviceAccessCode deviceAccessCode = deviceAccessCodeMapper.selectById(baseId);
        return deviceAccessCode;
    }

    @Override
    public AjaxResult insertRecord(DeviceAccessCode code) {
        String accessCode = code.getAccessCode();
        if(StringUtils.isNotBlank(accessCode)){
            DeviceAccessCodeDto condition = new DeviceAccessCodeDto();
            condition.setAccessCode(accessCode);
            List<DeviceAccessCode> existList = deviceAccessCodeMapper.selectByCondition(condition);
            if(!CollectionUtils.isEmpty(existList)){
                return AjaxResult.warn("该设备码已存在");
            }
        }else{
            return AjaxResult.warn("设备码不允许为空");
        }
        code.setCreateTime(new Date());
        deviceAccessCodeMapper.insert(code);
        return AjaxResult.success();
    }

    @Override
    public AjaxResult updateRecord(DeviceAccessCode code) {
        String status = code.getStatus();
        if(StringUtils.isNotBlank(status)){
            if(!SecurityUtils.hasRole("1")){
                return AjaxResult.warn("只有系统管理员才能进行审核");
            }
            DeviceAccessCode deviceAccessCode = deviceAccessCodeMapper.selectById(code.getBaseId());
            if(StringUtils.isNotBlank(status) && StringUtils.containsAny(deviceAccessCode.getStatus(), "1", "2")){
                return AjaxResult.warn("非待审核状态下不允许修改审核状态");
            }

        }
        deviceAccessCodeMapper.updateById(code);
        return AjaxResult.success();
    }

    @Override
    public int deleteByIds(List<Long> ids) {
        return deviceAccessCodeMapper.deleteBatchIds(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult deleteRecord(Long baseId) {
        DeviceAccessCode deviceAccessCode = deviceAccessCodeMapper.selectById(baseId);
        if(deviceAccessCode != null){
            String accessCode = deviceAccessCode.getAccessCode();
            deviceAccessCodeMapper.deleteById(baseId);
            visitorService.remove(new LambdaUpdateWrapper<DeviceAccessVisitor>().eq(DeviceAccessVisitor::getAccessCode, accessCode));
        }
        return AjaxResult.success();

    }

    @Override
    public AjaxResult validateCode(String code) {
        DeviceAccessCodeDto condition = new DeviceAccessCodeDto();
        condition.setAccessCode(code);
        condition.setFilterDate(new Date());
        condition.setStatus("1");
        List<DeviceAccessCode> deviceAccessCodes = deviceAccessCodeMapper.selectByCondition(condition);
        Map map = new HashMap();
        if(CollectionUtils.isEmpty(deviceAccessCodes)){
            return AjaxResult.warn("该设备码不存在或者已过期或者未审核通过");
        }else{
            DeviceAccessCode deviceAccessCode = deviceAccessCodes.get(0);
            Long accessInterval = deviceAccessCode.getAccessInterval();
            Integer accessCount = deviceAccessCode.getAccessCount();
            String accessUserName = deviceAccessCode.getAccessUserName();
            map.put("accessUserName", accessUserName);
            map.put("accessInterval", accessInterval);
            DeviceAccessVisitor visitorCondition = new  DeviceAccessVisitor();
            visitorCondition.setAccessCode(code);
            visitorCondition.setType("0");
            List<DeviceAccessVisitor> deviceAccessVisitors = deviceAccessVisitorMapper.selectByCondition(visitorCondition); 
            if(!CollectionUtils.isEmpty(deviceAccessVisitors)){
                int realAccessCount = deviceAccessVisitors.size();
                if(realAccessCount >= accessCount){
                    return AjaxResult.warn("该访问码已达到最大访问次数");
                }
                long totalInterval = deviceAccessVisitors.stream()
                        .mapToLong(DeviceAccessVisitor::getAccessInterval)
                        .sum();
                if(accessInterval!= -1 && totalInterval >= accessInterval){
                    return AjaxResult.warn("该访问码已达到最大访问时长");
                }

            }
            //返回监控列表
            String deviceId = deviceAccessCode.getDeviceId();
            List<Long> deviceIdList = Arrays.stream(deviceId.split(","))
                    .map(Long::valueOf)
                    .collect(Collectors.toList());
            List<MonitorArea> areaList = monitorAreaService.list(new LambdaQueryWrapper<MonitorArea>().in(MonitorArea::getBaseId, deviceIdList).eq(MonitorArea::getIsDelete, "0"));

            map.put("areaList", areaList);
            map.put("accessCode", code);
            return AjaxResult.success(map);
    
        }


    }

    @Override
    public AjaxResult fillCodeFlag(String ip) {
        DeviceAccessVisitor visitorCondition = new  DeviceAccessVisitor();
        visitorCondition.setIpAddress(ip);
        List<DeviceAccessVisitor> deviceAccessVisitors = deviceAccessVisitorMapper.selectByCondition(visitorCondition);
        if(CollectionUtils.isEmpty(deviceAccessVisitors)){
            return AjaxResult.success(true);
        }else{
            DeviceAccessCodeDto condition = new DeviceAccessCodeDto();
            condition.setFilterDate(new Date());
            condition.setStatus("0");
            boolean needFillCodeFlag = true;
            for (DeviceAccessVisitor deviceAccessVisitor : deviceAccessVisitors) {
                String accessCode = deviceAccessVisitor.getAccessCode();
                condition.setAccessCode(accessCode);
                condition.setFilterDate(new Date());
                condition.setStatus("1");
                List<DeviceAccessCode> deviceAccessCodes = deviceAccessCodeMapper.selectByCondition(condition);
                if(!CollectionUtils.isEmpty(deviceAccessCodes)){
                    DeviceAccessCode deviceAccessCode = deviceAccessCodes.get(0);
                    Long accessInterval = deviceAccessCode.getAccessInterval();
                    Integer accessCount = deviceAccessCode.getAccessCount();
                    DeviceAccessVisitor visitor = new  DeviceAccessVisitor();
                    visitor.setAccessCode(deviceAccessCode.getAccessCode());
                    visitorCondition.setType("1");
                    List<DeviceAccessVisitor> visitors = deviceAccessVisitorMapper.selectByCondition(visitor);
                    if(!CollectionUtils.isEmpty(visitors)){
                        int realAccessCount = visitors.size();
                        if(realAccessCount >= accessCount){
                            continue;
                        }
                        long totalInterval = visitors.stream()
                                .mapToLong(DeviceAccessVisitor::getAccessInterval)
                                .sum();
                        if(accessInterval!= -1 && totalInterval >= accessInterval){
                            continue;
                        }
                        needFillCodeFlag = false;
                        break;
                    }
                }
            }
            return AjaxResult.success(needFillCodeFlag);
        }
    }

    @Override
    public AjaxResult getAuthUrl(GetAuthUrlDto dto) {
        String accessCode = dto.getAccessCode();
        DeviceAccessCodeDto condition = new DeviceAccessCodeDto();
        condition.setAccessCode(accessCode);
        condition.setFilterDate(new Date());
        condition.setStatus("1");
        Long deviceId = dto.getDeviceId();
        MonitorArea device = monitorAreaService.getById(deviceId);
        if(device != null){
            String appName = device.getAppName();
            String streamName = device.getStreamName();
            String domain = device.getDomain();
            if("0".equals(dto.getSource())){
                List<DeviceAccessCode> deviceAccessCodes = deviceAccessCodeMapper.selectByCondition(condition);
                if(!CollectionUtils.isEmpty(deviceAccessCodes)){
                    DeviceAccessCode deviceAccessCode = deviceAccessCodes.get(0);
                    Long accessInterval = deviceAccessCode.getAccessInterval();
                    Date beginDate = new Date();
                    Date endDate = deviceAccessCode.getEndDate();
                    Long diffSeconds = Math.abs(endDate.getTime() - beginDate.getTime()) / 1000;
                    String authUrl = aliyunLiveService.getAuthUrl(domain, appName, streamName, "m3u8", accessInterval >= 0 ? ((diffSeconds - accessInterval) <= 0 ? diffSeconds : accessInterval) : diffSeconds);
                    return AjaxResult.success(authUrl);
                }else{

                    return AjaxResult.warn("该访问码不存在或者已过期");
                }
            }else if("1".equals(dto.getSource())){
                String authUrl = aliyunLiveService.getAuthUrl(domain, appName, streamName, "m3u8", 86400L);
                return AjaxResult.success(authUrl);
            }else{
                return AjaxResult.error("请检查传参");
            }
        }else{
            return AjaxResult.error("设备不存在");
        }




    }

    @Override
    public AjaxResult customerDevelopCount() {
        Long userId = SecurityUtils.getUserId();
        DeviceAccessCodeDto condition = new DeviceAccessCodeDto();
        List<Map> maps = deviceAccessCodeMapper.customerDevelopCount(condition);
        Map resultMap = new HashMap();
        boolean flag = false;
        if(!CollectionUtils.isEmpty(maps)){
            for(int i = 0; i <= maps.size() - 1; i++){
                if(userId.equals(maps.get(i).get("submitUserId"))){
                    flag = true;
                    Map map = maps.get(i);
                    map.put("rank", i+1);
                    resultMap.put("self", map);
                }
            }


        }
        condition.setLimitFlag(true);
        List<Map> limitList = deviceAccessCodeMapper.customerDevelopCount(condition);
        resultMap.put("list", limitList);
        if(!flag){
            Map selfMap = new HashMap();
            selfMap.put("developCount", 0);
            selfMap.put("submitUserName", null);
            selfMap.put("submitUserId", null);
            resultMap.put("self", selfMap);
        }

        return AjaxResult.success(resultMap);
    }
}